home *** CD-ROM | disk | FTP | other *** search
- Title ShowMCBs -- Program to scroll MCB Information
- Comment ! 28-Jan-1993 00:05:20
- Author: Tom Gilbert's Heart&Mind
- 7127 Lafayette Avenue
- Kansas City, KS 66109
- (913) 299-2701
-
- Copyright (c) 1988/93 by Heart & Mind
- for NON-Commercial Use ONLY
- Use and distribution in the
- Public Domain is encouraged!
-
- MCB Struc ; Information from MemoryControlBlock
- blkA DW 0 ; MCB Segment Address
- blkB DW 0 ; Block Type Letter & Code
- blkC DW 0 ; Controlled Area Segment
- blkL DW 0 ; Length of Controlled Area
- blkN DB 8 DUP (0) ; Identification of Area
- MCB EndS ; End of MCB Information Structure
- Cseg Segment Public Para
- Assume CS:Cseg, SS:Cseg ,DS:Nothing, ES:Nothing
- Org 100h
- Begin: Jmp Main
- exKeys DB 65,71,72,73,79,80,81 ; Extended Key Scan Codes
- LexKeys EQU $-exKeys ; Number of Codes in Table
- XMSmgr DB 3 ; 386MAX, 2=RM386, 1=QEMM386, 0=DOS
- SubF DB 0 ; Set to 1 If in Sub-Blocks
- Menv DW ? ; Segment of Master Environment
- Next DW ? ; Segment of Next Major MCB
- MCBS MCB 100 DUP (<>) ; Paragraph Aligned MCB Array
- SavePtr DW OFFSET MCBS
- XMS DD 0
- headline DB ' >ShowMCBs Version 5.2 for DOS 5.0 or equivalent'
- DB " - by Tom Gilbert's Heart&Mind",13,10
- DB ' Type Of Block Owner Program',13,10
- DB ' MCB Mem Area SEG Length Identity'
- DB ' Command Line Chained/Hooked INT Vectors',13,10
- DB ' ---- -------- ---- ------ --------'
- DB ' ---------------- --------------------------',13,10
- statline DB ' Line: of '
- DB ' Move: PgUg PgDn Home End or Exit: by Esc'
- DB ' or F7 to PrintMCBs '
- BytesE DB ' KiloBytes of Extended Memory available.',13,10
- DB ' KiloBytes in an available single block.',13,10
- BytesM DB ' bytes of conventional memory available at'
- MsgLen EQU $ - BytesM
- FkeyMsg DB 'Press F8 for output to filename ShowMCBs.PRN',0
- helpdat DB 13,10,255,' '
- DB 'Press F7 for report output to file or PRN.',13,10
- DB 13,10,' ',76 DUP ("*"),13,10
- DB ' IF you can ONLY get this HELP screen, '
- DB 'THEN you need DOS 5.0 or an equivalent',13,10
- DB ' ',76 DUP ("*"),13,10,13,10," "
- DB "ShowMCBs displays all MCBs in the 1st MEG of computer memory."
- DB 13,10,13,10
- DB ' "MCB" stands for "Memory Control Block". It controls',13,10
- DB ' the area beginning at the next paragraph.'
- DB 13,10
- DB ' The "Mem Area" lists the "Type Of" controlled block or sub-block.'
- DB 13,10,' '
- DB 'The "SEG" is the Segment at which an "Owner" area begins.'
- DB 13,10,' '
- DB 'If "0000" the next memory area is "available" for use.'
- DB 13,10,' '
- DB 'If "0008" or less the next memory area belongs to the system.'
- DB 13,10,' '
- DB 'The "Length" is decimal bytes for the area after the "MCB".'
- DB 13,10,' '
- DB ' A large area not followed by sub-blocks located in'
- DB 13,10,20 DUP (' '),'UPPER memory may be Video or an EMS page frame.'
- DB 13,10
- DB 13,10,' The "Identity" may be a "FileName" or'
- DB 13,10,' "DOS S"ystem"C"ode, or "S"ystem"D"ata.'
- DB 13,10,' "Filename" may be for an'
- DB 13,10,' "<Environment>" or "<FarDataArea>".'
- DB 13,10,' If "Filename" is a process,'
- DB 13,10,20 DUP (' '),' then "Command Line" is parameters.'
- DB 13,10,13,10,40 DUP (' '),' All INTerrupt vectors'
- DB 13,10,30 DUP (' '),' once WATCH is installed.'
- DB 13,10,30 DUP (' '),' Otherwise top of the chain.'
- DB 13,10,13,10
- DB " If expanded memory is installed, the Manager's Version number,"
- DB 13,10
- DB ' Page Frame Segment (through which memory is windowed) and block'
- DB 13,10
- DB ' information will be shown. User names are shown if provided.'
- DB 13,10,13,10
- DB ' The largest free Extended and Conventional memory'
- DB 13,10
- DB ' blocks display as "available" KiloBytes and bytes.'
- DB 13,10
- DB 13,10,' F7-F7 will print the display and F7-F8 makes ShowMCBs.PRN'
- DB 13,10,13,10
- DB ' ***** End of ShowMCBs Help *****',13,10
- helplen equ $-helpdat
- Sbuffer DW ? ; Start of Buffer
- Pbuffer DW ? ; Position in Buffer
- Lbuffer DW 8000h ; Length of Buffer
- Ebuffer DW ? ; End of Buffer
- LineNum DW ? ; Data buffer line
- LastNum DW ? ; Last buffer line
- columns EQU 80 ; Number of columns used per row
- rows DW 24 ; Number of last row for display
- datrows DW 20 ; Number of data rows per page
- lastrow DW 24 ; Number of last display row
- attr DB ? ; Video Attribute
- mode DB ? ; Initial mode
- pag DB ? ; Initial display page
- NewVid DB 0 ; Video change flag
- cga DB 1 ; CGA flag - default yes
- VidAdr DW 0B800h ; Color Video buffer address
- mono EQU 0B000h ; Monochrome address
- StatAtr DB 030h ; Color default - black on cyan
- BWstat EQU 070h ; B&W default - black on white
- ScrnAtr DB 017h ; Color default - white on blue
- BWscrn EQU 007h ; B&W default - white on black
- Watch DB "WATCH" ; WATCH Command Line Parameter
- WatchF DW 0 ; MCB Index to WATCH PSP if Set
- Vpos DW ? ; WATCH Next PSP-ID Position
- DisaM DB "*** D I S A B L E D ***"
- DisaLen EQU $-DisaM
- EMSerm DB 13,10,' *** Expanded Memory NOT Installed'
- DB ' or NOT Working ***',13,10
- emerml EQU $-EMSerm
- emmshdg DB 13,10,' block pages KBytes UserName '
- DB ' (Expanded Memory - Version '
- emmlen1 EQU $-emmshdg
- dashes DB 13,10,' ----- ----- ------ -------- '
- DB ' (LIM page frame address -'
- emmlen2 EQU $-emmshdg-emmlen1
- handles DW 0 ; E/Xms handles - default none
- EmsName DB 'EMMXXXX0' ; EMM standard Name
- Tpages DW 0 ; Page accumulator
- TotlM DB ' Total'
- FreeM DB ' Free '
- DOSm DB ' DOS '
- SubCBIs DB 'BCDEFILMSXZ' ; Codes 10=B -- Z=0
- TypeMCB DB 'Zmemory X FCBS= Stacks= Memory LastDrv '
- DB 'In-File Files= Extra ? Device= C Buff= Buffers '
- IsFar DB "<FarDataArea>"
- DB "<Environment>"
- DB "<386MAX Data>"
- DB "<Master Env.>"
-
- Main PROC
- Mov DI,Offset Buffer ; Save Offset of
- Mov Sbuffer,DI ; Display Buffer in
- Mov Pbuffer,DI ; Position to Start
- Mov CX,Lbuffer ; Initialize Length
- Shr CX,1 ; Use Word
- Mov AX," " ; Spaces to
- Rep StoSW ; SetUp Buffer
- Mov Ebuffer,DI
- Mov AX,352Eh
- Int 21h ; Get Segment of the
- Mov BX,ES:[2Ch] ; Master Environment
- Mov Menv,BX
- Mov ES,CS:[2Ch] ; Set Pointer to the
- Xor DI,DI ; ShowMCBs Environment
- Xor AX,AX ; Find Double NULL End
- Mov CX,8000h ; Before the File Spec.
- Find00: RepNE ScaSB ; Find First Null Byte
- Dec CX ; Count While Checking
- ScaSB ; If NOT Second NULL
- Jne Find00 ; Then Continue Scans
- Mov AL,"." ; Else Find Filename End
- RepNE ScaSB
- Dec DI ; Point to End "." and
- Mov CX,DI ; Initialize Counter
- Push DI ; Preserve Pointer and
- Push CX ; Counter Values
- STD ; Work Backwards
- Mov AL,"\" ; Look for Path
- RepNE ScaSB
- Mov SI,DI ; Save Position and
- Pop CX ; Restore Counter/Pointer
- Pop DI ; If Path Found
- Je FNless2 ; Then Filename Inside
- Mov AL,":" ; Else Search for Drive
- RepNE ScaSB
- Mov SI,DI ; Save Position and
- FNless2: Add SI,2 ; Adjust to FN 1st Byte
- Mov DI,SI ; Set Pointer and
- Sub CX,DI ; Calculate Length to
- CLD ; Compare Forward
- Mov SI,CS
- Dec SI ; Point to
- Mov DS,SI ; MCB Para.
- Mov SI,8 ; Filename
- RepE CmpSB
- Push CS ; If Filename
- Pop DS ; NOT in MCB
- Jne HelpOpt ; Then Give HELP
- Mov AX,4300h ; Else Check for
- Int 2Fh ; XMS Manager
- Cmp AL,80h ; If NOT Installed
- Jne GetData ; Then Leave Zero
- Mov AX,4310h ; Else Get Control
- Int 2Fh
- Mov Word Ptr XMS,BX ; Store Vector
- Mov Word Ptr XMS+2,ES
- Mov AH,8 ; Get Largest and
- Call XMS ; Total Kb Blocks
- Mov Word Ptr XMS+2,AX ; Save EMS Kb Report
- Mov Word Ptr XMS,DX
- GetData: Mov AH,52h ; From List of Lists
- Int 21h ; Get Address of the
- Mov BP,ES:[BX-2] ; First MCB to
- Mov CS:Next,BP ; Be Buffered
- Mov DS,BP ; Point to 1st
- Mov AX,DS:[24] ; Device Name
- Cmp AX,"83" ; If 386MAX
- Je GotMgr ; Then Default
- Dec CS:XMSmgr ; Else If
- Cmp AX,"MR" ; Is RM386
- Je GotMgr ; Then Set
- Dec CS:XMSmgr ; Else If
- Cmp AX,"EQ" ; QEMM386
- Je GotMgr ; Then Set
- Dec CS:XMSmgr ; Else DOS
- GotMgr: Push CS ; Set Extra
- Pop ES ; Segment for
- Mov DI,CS:SavePtr ; MCBS Storage
- Call GetMCBs
- HelpOpt: Mov SI,OFFSET helpdat ; Set Source to Help and
- Mov DI,Pbuffer ; Destination to Position
- Mov CX,helplen
- Rep MovSB ; Copy help data and
- Mov Ebuffer,DI ; Store End Position
- Sub DI,Sbuffer
- Mov Lbuffer,DI ; Store Length Used
- Mov DI,Ebuffer
- Call Lines2Top ; Count and Store
- Mov LastNum,AX ; Lines to Buffer End
- Mov AH,12h
- Mov BL,10h ; Call for EGA/VGA status
- Xor CX,CX ; With Clear status bits
- Int 10h
- Xor AX,AX
- JcxZ modechk ; If status is still Clear
- Mov ES,AX ; or if EGA is NOT active
- Test BYTE PTR ES:[487h],1000b
- Jnz modechk ; Then check CGA or Mono Mode
- Mov AX,1130h ; Else get EGA information
- Int 10h
- Mov AL,DL ; Make lines per screen
- CBW ; into a Word Value
- Mov rows,AX ; Reset number of the
- mov lastrow,AX ; last row and number
- Sub AX,4 ; of rows available for
- Mov datrows,AX ; data from their defaults
- Dec cga ; Clear the CGA Flag
- modechk: Push CS
- Pop ES
- Mov AH,0Fh ; Get video mode
- Int 10h
- Mov mode,AL ; Save initial
- Mov pag,BH ; mode and page
- Mov DL,AL ; Work on copy
- Cmp DL,7 ; If mono 7
- Je loadmono ; Then Set mono
- Cmp DL,15 ; Else If NOT mono 15
- Jne graphchk ; Then Check graphics
- loadmono: Mov VidAdr,mono ; Else Load mono address
- Mov StatAtr,BWstat ; Set B&W defaults for status
- Mov ScrnAtr,BWscrn ; line and screen background
- Dec cga ; Set as NOT CGA
- Cmp AL,15 ; If NOT mono 15
- Jne VidExit ; Then Done
- Mov DL,7 ; Else Set standard mono
- Jmp SHORT chmode
- graphchk: Cmp DL,7 ; If 7 or higher
- Jg color ; Then color or done
- Cmp DL,4 ; Else 5 and 6 are
- Jg bnw ; usually black and white
- Je color ; 4 is color
- Test DL,1 ; AND
- Jz bnw ; 0 and 2 are black and white
- color: Cmp DL,3 ; If mode 3
- Je VidExit ; Then Done
- Mov DL,3 ; Else use color text mode
- Jmp SHORT chmode
- bnw: Mov StatAtr,BWstat ; Set B&W defaults for status
- Mov ScrnAtr,BWscrn ; line and screen background
- Cmp DL,2 ; If mode 2
- Je VidExit ; Then Done
- Mov DL,2 ; Else use B&W text mode
- chmode: Mov AL,DL ; Set video mode
- Xor AH,AH
- Int 10h
- Mov AX,0500h ; Set video page 0
- Int 10h
- Mov AX,24 ; Color or Mono Rows
- Mov rows,AX ; Reset number of the
- mov lastrow,AX ; last row and number of
- Sub AX,4 ; rows available for data
- Mov datrows,AX ; from change before modechk
- Mov NewVid,1 ; Set flag
- VidExit: Mov DX,3200h ; Hide cursor
- Xor BH,BH ; off screen
- Mov AH,2
- Int 10h ; Display 1st page
- Jmp AtStart
- extended: Mov AH,7 ; Obtain Code for
- Int 21h ; extended Key
- Mov DI,OFFSET exKeys ; Load address and
- Mov CX,LexKeys ; length of key list
- RepNE ScaSB ; If a key match
- Je GotoKey ; Then go to work
- Jmp NextKey ; Else ignore key
- GotoKey: JcxZ PgDnK ; PgDnK is last
- Dec CX ; Backup through
- JcxZ DownK ; table until
- Dec CX ; locate one of
- JcxZ EndK ; seven keys and
- Dec CX ; do coresponding
- JcxZ PgUpK ; scroll routine
- Dec CX
- JcxZ UpK
- Dec CX ; If Next to Last
- JcxZ AtStart ; Then Is Home Key
- Call PrintMCBs ; If PrintMCBs Then Exit
- Jmp Quit
- DownK: Add CX,1 ; DN - Forward 1 line
- Jmp SHORT GoPage
- PgDnK: Add CX,datrows ; PGDN - Page forward
- Jmp SHORT GoPage
- UpK: Sub CX,1 ; UP - Go Back 1 line
- Jmp SHORT GoPage
- EndK: Mov DI,Ebuffer ; END - End of Buffer
- Mov Pbuffer,DI
- PgUpK: Sub CX,datrows ; PGUP - BackUp a Page
-
- GoPage: Mov DI,Pbuffer
- Mov AL,10 ; If Going UP Lines
- Jc GoBack ; Then Count Backwards
- CLD ; Else Count Forward
- FindF: Push CX ; Preserve Row Count
- Mov CX,82 ; Set Maximum Row Bytes
- RepNE ScaSB
- Pop CX ; If NO Linefeeds Below
- Jne AtEnd ; Then Must Be At End
- Loop FindF
- Mov Pbuffer,DI ; Set Position
- Call Lines2Top ; Get LineNumber
- Mov CX,LastNum ; If Last Line
- Sub CX,datrows ; Minus Display
- Cmp CX,LineNum ; Is => LineNumber
- Jnc Show ; Then Position Ok
- Mov AL,10
- AtEnd: Mov DI,Ebuffer ; From End of Buffer
- Mov CX,datrows ; Look Data Rows
- Neg CX ; Up or Backward
- GoBack: STD
- Sub DI,2 ; Back Off Any Newline
- Neg CX ; Make Count Positive
- FindB: Push CX ; Preserve Row Count
- Mov CX,82 ; Set Maximum Row Bytes
- RepNE ScaSB
- Pop CX ; If NO Linefeeds Above
- Jne AtStart ; Then Must Be At Start
- Loop FindB ; Else Loop Until
- CLD ; New Position
- Add DI,2 ; After Linefeed
- Mov Pbuffer,DI ; Set New Position
- Jmp SHORT Show
- AtStart: Mov DI,Sbuffer ; Reset Position to
- Mov Pbuffer,DI ; Start of Buffer
- Show: Call Lines2Top ; Count to Top Line
- Add AX,datrows ; Adjust to Bottom Line
- Cmp AX,LastNum ; If NOT past last
- Jle LineOk ; Then line is Ok
- Mov AX,LastNum ; Else make it Last
- LineOk: Mov DI,OFFSET statline[9]
- Xor DX,DX ; Store Line
- Call StoreVal ; Number and
- Mov AX,LastNum ; Number of
- Add DI,6 ; Last Line
- Call StoreVal
- Mov BL,StatAtr ; Set attribute for
- Mov attr,BL ; status & headings
- Xor BP,BP ; Initialize counter
- Mov SI,OFFSET headline ; Store heading lines
- HDloop: Mov AX,BP ; Set Video Line Number
- Call Line2Vid ; Write one line
- Inc BP ; Count the heading line
- Cmp BP,4 ; If NOT yet 4 lines
- Jc HDloop ; Then loop until 4
- Mov BL,ScrnAtr ; Change attribute for
- Mov attr,BL ; data buffer display
- Mov SI,Pbuffer ; Index to Position
- DatLoop: Mov AX,BP ; Set Video Line Number
- Call Line2Vid ; Write line
- Inc BP ; Count row displayed
- Cmp SI,Ebuffer ; If position => end
- Jnc PageDone ; Then page is done
- Cmp BP,rows ; Else If NOT Last Row
- Jc DatLoop ; Then loop Until done
- PageDone: Mov BL,StatAtr
- Mov attr,BL ; Load attribute for
- Mov SI,OFFSET statline ; writing status line
- Mov AX,BP
- Call Line2Vid ; Write status line
- NextKey: Mov AH,7
- Int 21h ; Get key code
- Cmp AL,27 ; If ESCape key
- Je Quit ; Then end ShowMCBs
- Or AL,AL ; Else If NOT null
- Jnz NextKey ; Then ignore key
- Jmp extended ; Else get extended
-
- Quit: Cmp NewVid,1 ; If video not changed
- Jne ThatsAll ; Then That's All
- Mov AL,mode ; Else Restore
- Xor AH,AH ; video mode
- Int 10h ; page and
- Mov AL,pag ; cursor
- Mov AH,5
- Int 10h
- ThatsAll: Mov CX,lastrow ; Load last row and
- Mov AX,rows ; Calculate rows to
- Sub AX,CX ; be scrolled blank
- Xchg CL,CH ; Set Upper Left and
- Mov DX,CX ; copy in order to
- Add DH,AL ; adjust Lower Right
- Mov DL,columns-1 ; corner of window
- Mov AH,6 ; Call ROM BIOS to
- Mov BH,7 ; clear the window
- Int 10h
- Mov DX,CX ; Set cursor above
- Dec DH ; window so prompt
- Xor BH,BH ; is on last line
- Mov AH,2 ; when Exit to DOS
- Int 10h
- Mov AX,4C00h ; Zero Error Level
- Int 21h ; Exit to MS-DOS
- Main ENDP
-
- Retrace PROC ; Writes during horizontal retrace (CGA)
- Push BX
- Mov BX,AX ; Save char/attr
- lscan2: In AL,DX ; Look in the port
- Shr AL,1 ; until it goes low
- Jc lscan2
- CLI
- hscan2: In AL,DX ; Look in the port
- Shr AL,1 ; until it goes high
- Jnc hscan2
- Mov AX,BX ; Restore and write
- StoSW ; Character/Attribute
- STI
- Pop BX
- Ret
- Retrace ENDP
-
- Line2Vid PROC
- Push ES ; Preserve SegReg Used
- Xor DX,DX ; Clear Flag for Scan
- Cmp cga,1 ; If NOT CGA
- Jne noscan ; Then leave zero
- Mov DX,03DAh ; Else load port #
- noscan: Mov ES,VidAdr ; Load Video Segment in
- Mov CX,80 ; Which to Write a Line
- Mov BX,80*2 ; Bytes per row Times
- Mul BL ; Starting Row Equals
- Mov DI,AX ; Starting Destination
- Mov AH,attr ; Set Video Attribute
-
- movechar: LodSB ; Get character
- Cmp AL,13 ; If End of Data Line
- Je fillspc ; Then end display line
- Or DX,DX ; Else if NOT CGA
- Je notCGA ; Then Write without delay
- Call Retrace ; Else Write during retrace
- Loop movechar ; Until End of Data Line
- Jmp SHORT chklf
- notCGA: StoSW ; If end of display line
- Loop movechar ; Then find End of Data Line
- Jmp SHORT chklf
- fillspc: Mov AL," " ; Fill with space
- Or DX,DX ; If NOT CGA Video
- Je space2 ; Then write direct
- space1: Call Retrace ; Else write during retrace
- Loop space1 ; Until end of display line
- Inc SI ; Adjust for Data line LF
- Jmp SHORT L2Vexit ; Return Position
- space2: Rep StoSW ; Write
- Inc SI ; Adjust for LF
- Jmp SHORT L2Vexit ; Return Position
- chklf: Mov AH,10
- LodSB ; Load and compare
- Cmp AL,AH ; If NOT Data Line LF
- LoopNE chklf ; Then Loop Until Find
- L2Vexit: Pop ES ; Restore SegReg Used
- Ret
- Line2Vid ENDP
-
- GetMCBs PROC
- Mov CS:SavePtr,DI ; Update MCBS Info Ptr
- Mov CS:SubF,0 ; Flag NOT in Sub-Blocks
- Mov BP,CS:Next ; Re-Group at Next MCB
- NUPSEG: Mov DS,BP
- Cmp BYTE PTR DS:[0],'Z' ; If End Block
- Je CkBack ; Then Real?
- Cmp BYTE PTR DS:[0],'M' ; Else If NOT 'M'
- Jne UpFast ; Then Search
- CkBack: Cmp WORD PTR DS:[1],8 ; If DOS Owner
- Jbe CkSize ; Or Owner Is
- Cmp WORD PTR DS:[1],BP ; After MCB
- Ja CkSize ; Then Real?
- UpFast: Mov CX,4
- Shr BP,CL ; Shift Bits to Even
- Shl BP,CL ; XXX0 Segment
- Add BP,10h ; Add 1/4 k
- Or BP,BP ; Search Until
- Jnz NUPSEG ; MCBs End
- Push CS
- Pop DS ; Restore DS to Data
- Jmp PutMCBs ; Store Information
-
- CkSize: Mov AX,DS ; If Size = MCB
- Inc AX ; Plus 1 Plus
- Add AX,DS:[3] ; Length Carries
- Jc UpFast ; Then NOT MCB
- Mov CS:Next,AX ; Else Set Next
- SetSeg: Mov DS,BP
- Xor SI,SI ; Point to MCB ID
- Mov AX,BP
- StoSW ; Store MCB's Address
- Inc BP ; Advance a Paragraph
- LodSB
- Push DI
- Lea DI,SubCBIs ; Set for Scanning
- Mov CX,11 ; Eleven ID Bytes
- RepNE ScaSB
- Pop DI ; If Valid ID
- Je SaveID ; Then Continue
- Sub DI,2 ; Else Re-Group
- Mov WORD PTR ES:[DI],0
- Jmp GetMCBs
- SaveID: Mov AH,CL ; Store the
- StoSW ; Letter/Code
- LodSW
- StoSW ; Store and Save
- Mov DX,AX ; Block Owner/SEG
- LodSW
- StoSW ; Store and Save
- Mov BX,AX ; Block Length
- Mov CX,8
- Add SI,3 ; Point to Name Area
- Push DS ; Preserve MCB Segment
- Cmp DX,0FFFAh ; If NOT 386MAX Data
- Jne TestFE ; Then Check Self-Load
- Mov DS,BP ; Else Next Paragraph
- Sub SI,4 ; has Name "UMB"
- Jmp Short LoadNB
- TestFE: Cmp DX,0FFFEh ; If Is Self-Loaded
- Je LoadNB ; Then Skip Other Tests
- Cmp DX,0FFFFh ; Else If NOT Device/Resvd.
- Jne TestSF ; Then Use MCB for Name
- Mov DS,BP ; Else Try Device Name
- Add SI,2
- Jmp Short LoadNB
- TestSF: Test CS:SubF,1 ; If in Sub-Blocks
- Jnz LoadNB ; Then Name Bytes
- Push SI ; Else Preserve
- Push DI ; Pointers and
- Push CX ; Counter for
- Mov CX,5 ; Check Whether
- Mov DI,OFFSET CS:Watch ; Name Is "WATCH"
- RepE CmpSB
- Jne NoMatch ; If Was "WATCH"
- Mov CS:WatchF,BP ; Then Store Segment
- NoMatch: Pop CX ; Else Restore Name
- Pop DI ; Length and Positions
- Pop SI
- LoadNB: LodSB
- Cmp AL,"!" ; If Space or Less
- Jb ChkSeg ; Or If Above Upper
- Cmp AL,"Z" ; Case Alphabetic
- Ja ChkSeg ; Then End Copying
- StoSB ; Else Copy Bytes
- Loop LoadNB ; Until 8 Or Invalid
- ChkSeg: Pop DS
- Add DI,CX ; Adjust to Next Array
-
- Mov AX,BP ; If Next Block Ok
- Add AX,BX ; Then Check If In
- Jnc CkSubs ; Sub-Blocks Or Next
- Mov CX,16 ; Else Re-Set 16
- Sub DI,CX ; Byte MCBs Array
- Push DI
- Xor AL,AL ; Null the Bytes and
- Rep StoSB ; Re-Group at Next MCB
- Pop DI
- Jmp GetMCBs
- CkSubs: Cmp AX,CS:Next ; If In SubBlocks
- Jc AddLen ; Then Continue
- Mov CS:SubF,0 ; Else End Subs
- Mov CS:Next,AX ; Set New Next
- Cmp BP,CS:Menv
- Je AddLen ; If Master Environment
- Or DX,DX ; Or If Was "Free" Block
- Jz AddLen ; Then Advance to Next MCB
- Cmp DX,8 ; Else If DOS is Owner
- Je LookNP ; Then Look at Next Paragraph
- Cmp BP,CS:[2] ; Else If In Conventional
- Jc AddLen ; Then Can't Be Sub-Block
- LookNP: Mov DS,BP ; Else Look at Next Paragraph
- Mov AL,DS:[0] ; Load Byte for Block ID
- Push DI
- Lea DI,SubCBIs ; Set for Scanning
- Mov CX,11 ; Eleven ID Bytes
- RepNE ScaSB
- Pop DI ; If NOT a Valid Sub-Block
- Jne AddLen ; Then Advance to Next MCB
- Mov CS:SubF,1 ; Else Work on Sub-Blocks
- Jmp SetSeg
- AddLen: Add BP,BX ; Work MCB at MCB+1 + Length
- Jmp SetSeg
- PutMCBs: Mov DI,OFFSET Buffer ; Point to Buffer and
- Mov SI,OFFSET MCBS ; Information for Display
- PMloop: Mov BX,SI ; Save Basic Index
- Cmp SI,SavePtr ; If Last MCB NOT Done
- Jb NextMCB ; Then Work Next MCB
- Jmp PMexit ; Else End Line and Exit
- NextMCB: LodSW
- Mov BP,AX ; Initialize as
- Inc BP ; Process Owner
- Call StoreHex ; Store MCB Address
- LodSB
- LodSB ; Convert MCB Type
- CBW ; Code to Word
- Mov CL,3 ; Offset to 8
- Shl AX,CL ; Byte Types
- Push SI
- Mov SI,OFFSET TypeMCB ; Point to Appropriate
- Add SI,AX ; MCB Type String
- Mov CX,8 ; Store 8 Byte
- Rep MovSB ; Type String
- Pop SI
- LodSW ; Load and Store
- Call StoreHex ; Hex Owner/SEG
- LodSW ; Load Length Word
- Add DI,6 ; Allow 6 Digits and
- Call StorePara ; Store Decimal Length
- Inc DI ; Advance to Identity
- Mov CX,8 ; Set Max Name Length
- Mov AX,[BX+4] ; Recover Owner Word
- Cmp AX,BP ; If Owner=MCB+1
- Je PNloop ; Then Name Stored
- Cmp AX,0FFFAh ; Else Other 386MAX
- Jae PNloop ; Load Name May Be Bad
- Cmp AX,CX ; Else If Above DOS Owner
- Ja PreNam ; Then May Have a Name
- Cmp AX,CX ; If DR-DOS Self-Load
- Je PNloop ; Then Name was Stored
- Mov CX,6 ; Else Store Six Bytes
- Push SI
- Lea SI,FreeM ; From " Free DOS "
- Dec DI ; Back-Up to Space
- Or AX,AX ; If Block Available
- Jz PutMsg ; Then Put "Free " in Name
- Add SI,CX ; Else Put " DOS " in Name
- PutMsg: Rep MovSB
- Pop SI ; Recover MCBS Pointer
- Mov CX,8 ; Set Max Name Length
- PreNam: Mov DX,OFFSET MCBS ; Point to First MCBS
- Cmp AX,CX ; If System 8
- Je PNloop ; Then SCorSD
- Ja PNfind ; Else Above Find
- Jmp PLdone ; Else 0-7 is Done
- PNfind: Mov SI,DX ; Set for
- Add DX,16 ; Next MCB Struc
- LodSW ; Get MCB Address
- Add SI,6 ; Point to Filename
- Inc AX ; If Para After MCB
- Cmp AX,[BX+4] ; Is the Process SEG
- Je PNloop ; Then Use its Name
- Cmp SI,SavePtr ; If Any More Used MCBS's
- Jb PNfind ; Then Continue Looking
- Jmp PLdone ; Else NOT Part of Process
- PNloop: LodSB
- Or AL,AL ; If NULL Byte
- Jz PNdone ; Then Done
- StoSB ; Else Store
- Loop PNloop
- PNdone: Mov AX,[BX+4] ; Load Owner Word
- Mov CX,13 ; Set Length for
- Mov SI,OFFSET IsFar+39 ; <Master Env.>, etc
- Cmp AX,-1 ; If Device/Reserved
- Je GoVecs ; Then No Command Line
- Mov DI,Pbuffer ; Else Point to
- Add DI,36 ; Command Line
- Cmp BP,Menv ; If Is <Master Env>
- Je MoveRem ; Then Write and Done
- Cmp BP,AX ; Else If MCB+1=Owner
- Je CmdLine ; Then Copy Command Line
- Sub SI,CX ; Else <386MAX Data> ?
- Cmp BP,CS:[2] ; If Conventional Block
- Jb NOT386 ; Then No 386MAX Data
- Cmp XMSmgr,3 ; Else If XMSmgr is 386 MAX
- Je MAX386 ; Then May Be <386MAX Data>
- NOT386: Sub SI,CX ; Else May Be <Environment>
- Cmp BP,AX ; If Below the Process
- Jb MoveRem ; Then <Environment>
- Sub SI,CX ; Else <FarDataArea>
- Jmp Short MoveRem
- MAX386: Cmp AX,0FFFEh ; If 386MAX Self-Loaded
- Je CmdLine ; Then Copy Command Line
- Cmp AX,0FFFAh ; Else If Self Load Data
- Je MoveRem ; Then Is <386MAX Data>
- Cmp BP,AX ; Or If Below Owner
- Jb MoveRem ; Then Is <386MAX Data>
- Sub SI,CX ; Else <Environment>
- MoveRem: Rep MovSB
- Cmp AX,8 ; If DOS Block
- Je PLdone ; Or If NOT
- Cmp SI,OFFSET IsFar+13 ; <FarDataArea>
- Ja PLdone ; Then NO Vectors
- Jmp Short GoVecs ; Else Check Vectors
- CmdLine: Push BX ; Preserve Index and
- Push DS ; Data Segment Register
- Mov DS,BP ; Point to Owner's
- Mov SI,80h ; Command Tail
- LodSB ; If Length of
- CBW ; Command Line
- Or AX,AX ; Word is Zero
- Jz CLexit ; Then No Parms
- Mov BX,AX ; Else If NO
- Cmp Byte Ptr [SI+BX],13 ; Ending CR
- Jne CLexit ; Then NO Parms
- Mov CX,16 ; Else If NOT
- Cmp AX,CX ; Over 16 Bytes
- Jbe ClenOk ; Then AX Bytes
- Mov AX,13 ; Else 13 Bytes
- Mov CX,".." ; Plus Elipsis
- ClenOk: Xchg AX,CX ; Copy AX Bytes of
- Rep MovSB ; Command Parameters
- Cmp AX,".." ; If NOT Elipsis(ed)
- Jne CLexit ; Then Line Finished
- StoSW ; Else Store
- StoSB ; Elipsis...
- CLexit: Pop DS ; Restore Data SEGment and
- Pop BX ; Restore Index
- GoVecs: Mov AX,CS
- Cmp AX,BP ; If PSP of ShowMCBs
- Je PLdone ; Then Avoid "Spurious"
- Call Vectors ; Chained/Hooked Vectors
- PLdone: Mov AX,0A0Dh ; Carriage Return and
- StoSW ; Line Feed Ends Line
- Mov Pbuffer,DI ; Keep Pbuffer Current
- Mov SI,BX ; Back-Up to Start at
- Add SI,16 ; Next MCBS' Member
- Jmp PMloop ; Loop Until MCBs Done
- PMexit: Mov AX,0A0Dh
- StoSW ; End Last Line
- Call PutEMMS ; Check EMMS Information
- Mov AX,Word Ptr XMS ; Load Total Free eXtended
- Or AX,Word Ptr XMS[2] ; If NO eXtended
- Jz PMecnv ; Then Skip Line
- Mov AX,Word Ptr XMS ; Else Load Total
- Xor DX,DX ; Prepare and
- Add DI,7 ; Position to
- Call StoreVal ; Store Kilo
- Lea SI,BytesE ; Bytes and
- Mov CX,MsgLen ; Trailing
- Rep MovSB ; Message
- Mov AX,Word Ptr XMS[2] ; Prepare and
- Add DI,7 ; Position to
- Call StoreVal ; Store Kilo
- Mov CX,MsgLen ; Bytes and
- Rep MovSB ; Message
- PMecnv: Mov AX,CS:[2] ; End of Conventional
- Mov CX,CS ; Memory Minus
- Sub AX,CX ; ShowMCBs PSP =
- Add DI,7 ; Paragraphs
- CAll StorePara ; as bytes of
- Lea SI,BytesM ; conventional
- Mov CX,MsgLen ; memory available
- Rep MovSB ; at ShowMCBs'
- Mov AX,CS ; ProgramSegmentPrefix
- Call StoreHex
- Mov Pbuffer,DI ; Update Pointer to Buffer
- Ret
- GetMCBs ENDP
-
- Vectors PROC
- Push BX ; Preserve MCB Index
- Mov DI,Pbuffer ; Position Show Index to
- Add DI,53 ; Start of Vector Area
- Cmp WatchF,0 ; If WATCH NOT Installed
- Jz UseHook ; Then Use Hooked Vectors
- Mov DS,WatchF ; Else Use Chained
- Mov SI,104h ; Get Next Vector
- LodSW ; Position in
- Mov SI,320h ; Vector Change
- Add AX,SI ; Storage Area
- Mov CS:Vpos,AX ; Store for Comparison
- Sub SI,8 ; Get a Running Start
- Xor BX,BX ; Zero Vector Counter
- FFLoop: Add SI,8 ; If Next Record
- Cmp SI,CS:Vpos ; Is Table End
- Jnc UseHook ; Then Check Hooked
- CkPSPID: Cmp Word Ptr [SI],-1 ; If NOT pspid
- Jne FFLoop ; Or If NOT the
- Cmp [SI+2],BP ; Desired SEGment
- Jne FFLoop ; Then Keep Looking
- WatchL: Add SI,8 ; Else If Next Record
- Cmp SI,CS:Vpos ; Is Past Table End
- Jnc LillyPad ; Or If Next PSPID
- Cmp WORD PTR [SI],-1 ; Then Exit Done
- Je INTExit
- Cmp BYTE PTR [SI+1],1 ; If Disabled Vector
- Je WatchX ; Then "DISABLED" Exit
- Cmp BX,9 ; Else If More Columns
- Jc WatchW ; Then Store Vector
- Mov WORD PTR ES:[DI],0A0Dh ; Else End Line
- Mov CS:Pbuffer,DI ; UpDate to NewLine
- Add DI,55 ; Start new line
- Xor BX,BX ; Update counter
- WatchW: Mov AX,[SI] ; Get Vector Number
- Call Val2ASCh ; Store 2 HEX Digits + Space
- Inc BX ; Count Vector
- Jmp WatchL ; Loop until exit
- WatchX: Push CS
- Pop DS ; Restore Data Segment
- Mov SI,OFFSET DisaM ; Copy the Message
- Mov CX,DisaLen ; " D I S A B L E D "
- Rep MovSB ; and Exit Vectors
- LillyPad: Jmp Short INTExit
-
- UseHook: Pop BX ; Restore Index to
- Push BX ; Use for to get
- Mov DX,ES:[BX+6] ; Program Length
- Cmp DX,800h ; If .COM Size
- Jc UHlimit ; Then in Limits
- Mov DX,800h ; Else Shorten
- UHlimit: Add DX,BP ; Start+Len = Limit
- Cmp BP,0B800h ; If Below CGA/VGA
- Jb UHnoVid ; Then Probably Ok
- Cmp DX,0C000h ; Else If In Video
- Jbe INTExit ; Then No Vectors
- UHnoVid: Xor BX,BX ; Initialize INT at
- Mov DS,BX ; Beginning of DOS
- Mov SI,BX ; Interrupt Table &
- Mov CX,256 ; Double Word Count
- UH_Loop: LodSW
- LodSW ; If SEG of INT
- Cmp AX,BP ; Is Below Program
- Jb Loop2UH ; Or If Above Limit
- Cmp AX,DX ; Then Loop for Next
- Ja Loop2UH ; Until End of INTs
- Mov AX,BX ; Else Store 2 HEX
- Call Val2ASCh ; Digits + Space
- Mov AX,CS:Pbuffer ; If start of current row
- Add AX,columns-2 ; Up to position after end
- Cmp DI,AX ; Is greater than pointer
- Jc Loop2UH ; Then Loop Until EOL/Done
- Mov AX,0A0Dh ; Else Start a New Line
- StoSW
- Mov CS:Pbuffer,DI ; UpDate to NewLine
- Add DI,53 ; Position to INT Nos.
- Loop2UH: Inc BX ; Increment INT Number
- Loop UH_Loop ; Loop to End of Table
- INTExit: Push CS
- Pop DS ; Restore
- Push CS ; Segments to
- Pop ES ; ShowMCBs PSP
- Pop BX ; Restore Index
- Ret
- Vectors ENDP
-
- Val2ASCh PROC ; Machine Code to Divide
- DB 0D4h,10h ; AL/16 AL=MS and AH=LS
- Or AX,3030H ; Convert to ASCII
-
- Cmp AL,"9" ; If Decimal ASCII
- Jbe ALexit ; Then Digit is Ok
- Add AL,7 ; Else Make "A" - "F"
- ALexit: Cmp AH,"9"
- Jbe AHexit ; Do Same With MS Digit
- Add AH,7
- AHexit: Xchg AL,AH ; Reverse MS and LS Digits
- StoSW ; Store 2 HEX ASCII Digits
- Inc DI ; Terminate With a Space
- Ret
- Val2ASCh ENDP
-
- PutEMMS PROC
- Push DI ; Preserve Storage
- Push ES ; Segment:Pointer
- Mov AX,3567h ; Get Vector for
- Int 21h ; Function 67hex
- Mov DI,000Ah ; Scan Device
- Mov CX,8 ; Name for:
- Lea SI,EmsName ; "EMMXXXX0"
- Rep CmpSB
- Pop ES ; Restore ES:DI
- Pop DI ; If NOT "EMMXXXX0"
- Jne EmsErrX ; Then Error Exit
- Mov AH,46h ; Or If version
- Int 67h ; number request
- Or AH,AH ; returns error
- Jnz EmsErrX ; Then Error Exit
- Mov SI,OFFSET emmshdg ; Else store 1st
- Mov CX,emmlen1 ; Heading Line
- Rep MovSB
- Call SHex_1 ; Store Major/Minor
- Dec DI ; EMMS Version and
- Mov AH,ES:[DI] ; Insert Dot
- Mov AL,"." ; Move Minor
- StoSW ; Number
- Mov AL,')' ; Close Parens.
- StoSB
- Mov CX,emmlen2 ; Add 2nd heading
- Rep MovSB ; line lead-in to
- Mov AH,41h ; EMS Page Frame
- Int 67h
- Or AH,AH ; If Request Fails
- Jnz EmsErrX ; Then Error Exit
- Mov AX,BX ; Else store HEX
- Call StoreHex ; page frame plus
- Mov AL,")" ; close parenthesis
- Mov ES:[DI-1],AL
- Mov AX,0A0Dh ; End the line
- StoSW
- Mov AH,4Bh ; Get Handle
- Int 67h ; Count in BX
- Or AH,AH ; If Response
- Jz EmPages ; Then Map Pages
- EmsErrX: Mov SI,OFFSET EMSerm ; Else store EMS
- Mov CX,emerml ; Error Message
- Rep MovSB
- Jmp EmmExit
- EmPages: Mov CX,BX ; Set Handle Counter
- Inc CX ; for zero thru [bx]
- Mov handles,CX
- HndLoop: Mov AH,4Ch ; Get
- Mov DX,handles ; Assigned
- Sub DX,CX ; Handle
- Int 67h ; Pages
- Or AH,AH ; If Error
- Jnz NoPages ; Then skip
- Or BX,BX ; Else if > 0
- Jnz PagesOk ; Then store
- NoPages: Loop HndLoop ; Else loop until
- Jmp SHORT HndExit ; CX handles done
- PagesOk: Xor AX,AX
- Push DX ; Preserve and
- Add DI,6 ; Position for
- Xchg AX,DX ; Handle Number
- Call StoreVal
- Add DI,9 ; Position
- Mov AX,BX ; for pages
- Call StoreVal
- Add Tpages,BX ; Accumulate Total
- Add DI,9 ; Position for
- Mov AX,BX ; Handle KBytes
- Call StorePara
- Add DI,3 ; Position for
- Mov AX,5300h ; User Name
- Pop DX
- Int 67h ; Advance Past
- Add DI,8 ; Name Area
- Mov AX,0A0Dh ; End the line
- StoSW ; Loop until
- Loop HndLoop ; CX'em done
-
- HndExit: Mov AH,42h ; Get Free
- Int 67h ; Pages and
- Add Tpages,BX ; Adjust Total
- Mov SI,OFFSET FreeM
- Mov CX,6 ; Store " free"
- Rep MovSB ; lead-in and
- Add DI,9 ; Position for
- Mov AX,BX ; Free Pages
- Xor DX,DX
- Call StoreVal
- Add DI,9 ; Position for
- Mov AX,BX ; Free KBytes
- Call StorePara
- Mov SI,OFFSET dashes+26 ; Space Over
- Mov CX,11 ; and dash-out
- Rep MovSB ; UserName
- Mov AX,0A0Dh ; End the line
- StoSW
- Mov SI,OFFSET TotlM ; Store
- Mov CX,6 ; " total"
- Rep MovSB ; lead-in
- Add DI,9 ; Position for
- Mov AX,Tpages ; Total Pages
- Call StoreVal
- Add DI,9 ; Position for
- Mov AX,Tpages ; Total KBytes
- Call StorePara
- Mov SI,OFFSET dashes+26 ; Space Over
- Mov CX,11 ; and dash-out
- Rep MovSB ; UserName
- EmmExit: Mov AX,0A0Dh ; End the line
- StoSW ; and Add a
- StoSW ; New Line
- Ret
- PutEMMS ENDP
-
- Lines2Top PROC
- Mov AX,10 ; Count Line Feeds
- Push CX ; Preserve Counter and
- Push DI ; If Buffer Pointer
- Mov CX,DI ; Is at Buffer Start
- Sub CX,Sbuffer ; Then NO Lines Above
- JcxZ L2Tdone ; Else Use Counter to
- Std ; Scan Back for Line Feeds
-
- L2Tloop: RepNE ScaSB ; If NO MORE Line Feeds
- Jne L2Tdone ; Then All Were Counted
- Inc AH ; Else Accumulate Number
- JcxZ L2Tdone ; Until Reach the Top
- Jmp L2Tloop
- L2Tdone: Mov AL,AH ; Make Line Count
- Xor AH,AH ; Into a Word Value
- Mov LineNum,AX ; Store Line Number
- Cld ; Restore Direction
- Pop DI ; Buffer Pointer
- Pop CX ; and Counter
- Ret ; AX = 0 to 255 Lines
- Lines2Top ENDP
-
- StorePara PROC
- Push DX ; Preserve
- Push AX ; Registers
- Push CX ; Used
- Mov CX,16 ; Convert to Bytes as
- Mul CX ; DoubleWord in DX:AX
- Pop CX
- Call StoreVal ; Store DWord Value
- Pop AX ; Restore
- Pop DX ; Registers
- Ret ; Used
- StorePara ENDP
-
- StoreVal PROC ; Preserve
- Push DI ; Registers
- Push CX ; Used
- Mov CX,10 ; Decimal Base 10
- Cmp CX,DX ; If DX:AX is Too Big
- Jb SVabort ; Then Abort Routine
- SVloop: Dec DI ; Else Back-Up Pointer
- Div CX ; Make Remainder
- Or DL,'0' ; ASCII Digit
- Mov ES:[DI],DL ; Store in Buffer
- Xor DX,DX ; Zero Remainder
- Or AX,AX ; Loop Until Zero
- Jnz SVloop
- SVabort: Pop CX ; Restore
- Pop DI ; Registers
- Ret ; Used
- StoreVal ENDP
-
- StoreHex PROC ; AX Will Be Changed
- Push AX ; Preserve the Word
- Inc DI ; Add Leading Space
- Mov AL,AH ; Work on MSByte
- Call SHex_1 ; Store 2 Digits
- Pop AX ; Restore Value
- Call SHex_1 ; Store LSByte Digits
- Mov AL,' ' ; Add Trailing Space
- Jmp SHORT SHexit
- SHex_1: Mov AH,AL ; Save Working Byte
- And AL,0F0h ; Isolate
- Shr AL,1 ; Upper
- Shr AL,1 ; Nibble
- Shr AL,1 ; In the
- Shr AL,1 ; AL Reg
- Call SHex_2 ; Store as ASCII Digit
- Mov AL,AH ; Restore Byte and
- And AL,0Fh ; Isolate Lower Nibble
- SHex_2: Add AL,'0' ; Make ASCII Digit
- Cmp AL,'9'+1 ; Check If Decimal
- Jb SHexit ; Decimal Ok to Store
- Add AL,'A'-'9'-1 ; Else Make Hex 'A-F'
- SHexit: StoSB ; Store AL Character
- Ret ; Recurse or Return
- StoreHex ENDP ; Value is Destroyed
-
- PrintMCBs PROC
- Mov AX,1300h ; Write Message
- Mov BH,pag ; Video Page and
- Mov BL,StatAtr ; Attribute that
- Mov BP,OFFSET FkeyMsg ; Requests Choice
- Mov CX,MsgLen+2 ; F7=PRN or F8=file
- Mov DX,lastrow ; Bottom Row in
- Xchg DH,DL ; DH and Column
- Mov DL,16 ; 16 in DL with
- Int 10h ; ES:BP as Pointer
- Mov BX,4 ; PRN Device Default
- PrintKey: Mov AH,7
- Int 21h
- Or AL,AL ; Wait for Function Key
- Jnz PrintKey
- Mov AH,7
- Int 21h
- Cmp AL,65 ; If F7
- Je PrintBeg ; Then PRN
- Cmp AL,66 ; Else If NOT F8
- Jne PrintKey ; Then Wait for Choice
- Mov DX,OFFSET helpdat-13
- Mov AH,3Ch ; Create ShowMCBs.PRN
- Xor CX,CX ; Normal Attributes
- Int 21h ; If Create Fails
- Jc PrintBeg ; Then Use PRN
- Mov BX,AX ; Else Use file
- PrintBeg: Mov DI,Sbuffer ; Scan from Start
- Call PrintChk ; SetUp for Scans
- Scan4CR: RepNE ScaSB
- Inc DX ; Count New Lines
- Cmp ES:[DI+1],AH ; If Reach helpdat
- Je PrintOut ; Then End Printing
- Cmp DX,50 ; Else If < 50 Lines
- Jb Scan4CR ; Then Continue Scan
- ScaSB ; Else Look for a
- Sub CX,2 ; Double CR,LF
- ScaSB ; If Double CR,LF
- Je DoPrint ; Then Print a Page
- Add CX,2 ; Else Put Back
- Sub DI,2 ; Count and Ptr
- Cmp DX,58 ; Until 58 Lines
- Jb Scan4CR ; Continue Scan
- DoPrint: Call PrintOut ; Print to Here
- Jmp Scan4CR
- PrintOut: Mov AL,12 ; Change LF to FF
- StoSB ; Count the
- Dec CX ; FormFeed
- Push CX ; Save Count
- Mov AH,40h ; Write to BX
- Mov CX,OFFSET statline ; Contents of
- Mov DX,OFFSET headline ; Heading
- Sub CX,DX ; 4 Lines
- Int 21h
- Pop CX ; Restore Byte Count
- Not CX ; Set Length to Print
- Mov DX,DI ; Set DX to
- Sub DX,CX ; Start Place
- Mov AH,40h ; Write CX
- Int 21h ; Buffer Bytes
- PrintChk: Cmp Byte Ptr ES:[DI],255 ; If NOT at End of Data
- Jne PrintSet ; Then Set to Scan More
- Cmp BX,4 ; Else If PRN Device
- Je PrintSet ; Then Go to Exit
- Mov AH,3Eh ; Else Close File
- Int 21h
- PrintSet: Mov CX,-1 ; Counting from
- Mov DX,4 ; After Heading for
- Mov AX,0FF0Dh ; Carriage Returns
- Ret
- PrintMCBs ENDP
- DB 25,'Start V Buffer',25
- Buffer:
- Cseg ENDS
- END Begin